package org.cebu.tourism.maps.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.maps.client.InfoWindowContent;
import com.google.gwt.maps.client.MapWidget;
import com.google.gwt.maps.client.Maps;
import com.google.gwt.maps.client.control.SmallMapControl;
import com.google.gwt.maps.client.geom.LatLng;
import com.google.gwt.maps.client.overlay.EncodedPolyline;
import com.google.gwt.maps.client.overlay.Marker;
import com.google.gwt.maps.client.overlay.Polyline;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DockLayoutPanel;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.TextBox;
import org.cebu.tourism.maps.data.MapDataWrapper;

/**
 * Entry Point for Tourism App
 */
public class Tourism extends MapDataWrapper implements EntryPoint{
	 
	  private static MapWidget map;
	  private DockLayoutPanel dock;
	  private FormPanel form;
	  private MapServiceAsync service;
	  private TextBox searchBox;
	  private Marker marker;
	  
	  private final String MAP_TARGET_PATH = "/tourism/maps";
	  private final String INIT_REQUEST = "Cebu";
	  private final String MAP_SIZE_WIDTH = "100%";
	  private final String MAP_SIZE_HEIGHT = "100%";
	  private final String IMG_INFO_WIDTH = "50px";
	  private final String IMG_INFO_HEIGHT = "50px";
	  private final int INIT_ZOOM_LEVEL = 9;
	  
	  
	  // GWT module entry point method.
	  public void onModuleLoad() 
	  {
		  dock = new DockLayoutPanel(Unit.PX); 
		  if(null == map)
		  {
		    /*
	         * Asynchronously loads the Maps API.
	         *
	         * The first parameter should be a valid Maps API Key to deploy this
	         * application on a public server, but a blank key will work for an
	         * application served from localhost.
	         */
	         Maps.loadMapsApi("", "2", false, new Runnable() {
		        public void run()
		        {
		    	   UIInitMap();
		    	   UIGenerateRoute("naga", "Minglanilla");
		    	   dock.addNorth(map, 500); 
		        }
	         });
		  }	   
		  
		  //init form widgets
	      UIAddFormPanel();
		  // Add the map to the HTML host page
		  RootLayoutPanel.get().add(dock);
	  }

      /*
       * @author: jdelapena 04/09/12 
       * @function Name: UIAddFormPanel
       * @description: Add Form Panel widgets for location query.
       *               Method used is GET. 
       *               RPC doesn't override POST method.
       */
	  private void UIAddFormPanel()
	  {
		  //Create Async Service
		  service = (MapServiceAsync) GWT.create(MapService.class);
		  
		  //Init Form Panel
		  form = new FormPanel();
		  form.setEncoding(FormPanel.ENCODING_MULTIPART);
		  form.setMethod(FormPanel.METHOD_GET);
		  form.setAction(MAP_TARGET_PATH);
		  searchBox = new TextBox();
		  searchBox.setName("searchId");
		  
		  //Add Submit Complete Handler
		  form.addSubmitCompleteHandler(new SubmitCompleteHandler()
		  {
		     @Override
			    public void onSubmitComplete(SubmitCompleteEvent event)
		        {
				   service.getRequestId(new AsyncCallback<String>(){
				      public void onFailure(Throwable caught)
				      {
					     System.out.println("Query Failure: " + caught.toString());
					  }

					  public void onSuccess(String locationId)
					  {
					     System.out.println("[onSuccess] Query Request: " + locationId);
					     //remove marker overlay for new request
					     if(null != marker)
					     {
					        map.removeOverlay(marker);
					     }
					     UIAddMarker(locationId);
					     UIAddInfoWindow(locationId);
					  }				
				});
			}	    
		  });
		  
		  //Create Horizontal Panel for form widgets
		  HorizontalPanel panel = new HorizontalPanel();
		  Button submitButton = new Button("Submit");
		  submitButton.addClickHandler(new ClickHandler()
		  {
		     @Override
			 public void onClick(ClickEvent event) {
			    form.submit();
			 }	
		  });
		  
		  panel.add(new Label("Search"));
		  panel.add(searchBox);
		  panel.add(submitButton);
		  
		  form.add(panel);
		  dock.addEast(form, 500);
	  }

      /*
       * @author: jdelapena 04/09/12 
       * @function Name: UIInitMap
       * @description: Init map properties.
       *               Add map control.
       */
	  private void UIInitMap()
	  {
		  //Center map to Cebu
		  LatLng coords = search(INIT_REQUEST);
		  map = new MapWidget(coords, INIT_ZOOM_LEVEL);
		  map.setSize(MAP_SIZE_WIDTH, MAP_SIZE_HEIGHT);    		    
		  map.addControl(new SmallMapControl());
		  map.setScrollWheelZoomEnabled(true);
	  }
	    
      /*
       * @author: jdelapena 04/09/12 
       * @function Name: UIAddMarker
       * @description: Search marker is added to map
       */
	  private void UIAddMarker(String query)
	  {
		  //get search marker
		  marker = getMarker(query.toLowerCase());
		  map.addOverlay(marker);
	  }
	  
      /*
       * @author: jdelapena 04/09/12 
       * @function Name: UIAddInfoWindow
       * @description: InfoWindow is added to map
       */
	  private void UIAddInfoWindow(String query)
	  {
		  //Add Horizontal Panel
		  HorizontalPanel panel = new HorizontalPanel();
		  Image img = new Image("images/"+query.toLowerCase()+".jpg");
		  img.setWidth(IMG_INFO_WIDTH);
		  img.setHeight(IMG_INFO_HEIGHT);
		  panel.add(img);
		  
		  //Add HTML snippet
		  HTML html = new HTML("<p>&nbsp;&nbsp;<b>Hello "+query+"!!!</b></p>");
		  panel.add(html);
		  
		  //Create InfoWindowContent
		  InfoWindowContent content = new InfoWindowContent(panel);
		  
		  // Add an info window to highlight a point of interest
		  map.getInfoWindow().open(marker, content);   
	  }
	  
	  private void UIGenerateRoute(String src, String dest)
	  {
		  //TODO: create json object for routes
		  //      disect route per segment to the maximum zoom level
		  //      json structure
		  //      "place": "name"
		  //      coords: [x, y, z]
		  //      graph implementation
		  //      Query: create own encoding/decoding
		  String route = src + " to " + dest;
		  String level = getEncodeLevel(route.toLowerCase());
		  String encode = getEncodeString(route.toLowerCase());
		  
		  System.out.println("Route: " + route);
		  
		  //add src and dest markers
		  map.addOverlay(getMarker(src));
		  map.addOverlay(getMarker(dest));
		  
		  //add route  		  
		  EncodedPolyline enc = EncodedPolyline.newInstance(encode, 3, level, 3);
		  enc.setColor("#000066");
		  enc.setWeight(5);
		  map.addOverlay(Polyline.fromEncoded(enc));
	  }
}

